﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Input;
using System.Reflection;
using System.ComponentModel;
using Sinacor.Infra.UI.Common;
using System.Windows;
using PSE.Framework.UI.Resources;
using System.Collections;
using Sinacor.Infra.Common;

namespace Sinacor.Infra.UI.Controls.SmartClient
{
    public partial class SinacorDataGrid
    {
        #region Tratamento de Eventos

        #region CopyClipboardCommand

        #region CopyClipboardCommand_CanExecute
        private void CopyClipboardCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            SinacorDataGrid grid = (SinacorDataGrid)sender;
            e.CanExecute = grid.IsCopyableClipboard && grid.CanCopyClipboard();
            e.Handled = true;
        }
        #endregion

        #region CopyClipboardCommand_Executed
        private void CopyClipboardCommand_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            SinacorDataGrid grid = (SinacorDataGrid)sender;
            grid.CopyClipboard();
        }
        #endregion

        #endregion

        #region CopyAllClipboardCommand

        #region CopyAllClipboardCommand_CanExecute
        private void CopyAllClipboardCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            SinacorDataGrid grid = (SinacorDataGrid)sender;
            e.CanExecute = grid.IsCopyableClipboard && grid.CanCopyAllClipboard();
            e.Handled = true;
        }
        #endregion

        #region CopyAllClipboardCommand_Executed
        private void CopyAllClipboardCommand_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            SinacorDataGrid grid = (SinacorDataGrid)sender;
            grid.CopyAllClipboard();
        }
        #endregion

        #endregion

        #endregion

        #region IsCopyableClipboard
        public static readonly DependencyProperty IsCopyableClipboardProperty = DependencyProperty.Register("IsCopyableClipboard", typeof(Boolean), typeof(SinacorDataGrid), new FrameworkPropertyMetadata(true, null, CoerceIsCopyableClipboard));
        /// <summary>
        /// Indica se o grid suporta cópia para área de transferência
        /// </summary>
        public Boolean IsCopyableClipboard
        {
            get { return (Boolean)GetValue(IsCopyableClipboardProperty); }
            set { SetValue(IsCopyableClipboardProperty, value); }
        }

        private static object CoerceIsCopyableClipboard(DependencyObject d, object value)
        {
            SinacorDataGrid grid = d as SinacorDataGrid;
            bool isCopyableClipboard = false;

            foreach (Column column in grid.Columns)
            {
                if (column.AllowCopyClipboard)
                {
                    isCopyableClipboard = true;
                    break;
                }
            }

            value = isCopyableClipboard;
            return value;
        }
        #endregion

        #region CopyingClipboardEvent
        public static readonly RoutedEvent CopyingClipboardEvent = EventManager.RegisterRoutedEvent("CopyingClipboard", RoutingStrategy.Bubble, typeof(CancelItemsEventHandler), typeof(SinacorDataGrid));
        /// <summary>
        /// Evento disparado antes da cópia para área de transferência
        /// </summary>
        public event CancelItemsEventHandler CopyingClipboard
        {
            add { AddHandler(CopyingClipboardEvent, value); }
            remove { RemoveHandler(CopyingClipboardEvent, value); }
        }

        /// <summary>
        /// Dispara o evento <c>CopyingClipboard</c>
        /// </summary>
        /// <param name="itemsInfo">Itens sendo copiados</param>
        /// <returns>true se evento não foi cancelado</returns>
        protected virtual bool OnCopyingClipboard(IList<ItemInfo> itemsInfo)
        {
            CancelItemsEventArgs e = new CancelItemsEventArgs(SinacorDataGrid.CopyingClipboardEvent, this, itemsInfo);
            RaiseEvent(e);
            return !e.Cancel;
        }
        #endregion

        #region CopiedClipboardEvent
        public static readonly RoutedEvent CopiedClipboardEvent = EventManager.RegisterRoutedEvent("CopiedClipboard", RoutingStrategy.Bubble, typeof(ItemsEventHandler), typeof(SinacorDataGrid));
        /// <summary>
        /// Evento disparado depois da cópia para área de transferência
        /// </summary>
        public event ItemsEventHandler CopiedClipboard
        {
            add { AddHandler(CopiedClipboardEvent, value); }
            remove { RemoveHandler(CopiedClipboardEvent, value); }
        }

        /// <summary>
        /// Dispara o evento <c>CopiedClipboard</c>
        /// </summary>
        /// <param name="itemsInfo">Itens sendo copiados</param>
        protected virtual void OnCopiedClipboard(IList<ItemInfo> itemsInfo)
        {
            ItemsEventArgs e = new ItemsEventArgs(SinacorDataGrid.CopiedClipboardEvent, this, itemsInfo);
            RaiseEvent(e);
        }
        #endregion

        #region CopyClipboard
        /// <summary>
        /// Indica se pode copiar os itens selecionados para área de transferência
        /// </summary>
        /// <returns>true se puder copiar para área de transferência, false se não puder</returns>
        protected bool CanCopyClipboard()
        {
            return !this.IsEditing && (this.Items.Count > 0) && (this.SelectedItems.Count > 0);
        }
       
        /// <summary>
        /// Copia os itens selecionados para área de transferência
        /// </summary>
        /// <returns>
        /// true se copiou com sucesso, false se a cópia foi cancelada no evento <c>CopyingClipboard</c> 
        /// ou se não existem itens selecionados
        /// </returns>
        public bool CopyClipboard()
        {
            if (this.CanCopyClipboard())
            {
                return this.CopyClipboard(this.SelectedItems);
            }
            return false;
        }

        /// <summary>
        /// Copia o item indicado pelo índice para área de transferência
        /// </summary>
        /// <param name="index">Índice do item</param>
        /// <returns>true se copiou com sucesso, false se a cópia foi cancelada no evento <c>CopyingClipboard</c></returns>
        public bool CopyClipboard(int index)
        {
            return this.CopyClipboard(new int[] { index });
        }

        /// <summary>
        /// Copia os itens indicados pelos índices para área de transferência
        /// </summary>
        /// <param name="indexs">Índices dos itens</param>
        /// <returns>true se copiou com sucesso, false se a cópia foi cancelada no evento <c>CopyingClipboard</c></returns>
        public bool CopyClipboard(int[] indexs)
        {
            if (indexs == null)
                throw new ArgumentNullException("indexs");
            if (indexs.Length == 0)
                throw new ArgumentException("Indexs cannot be empty", "indexs");

            if (!this.IsEditing && this.Items.Count > 0)
            {
                object[] items = Array.ConvertAll<int, object>(indexs,
                            delegate(int input)
                            {
                                return this.GetItem(input);
                            });

                return this.CopyClipboard(items);
            }

            return false;
        }

        /// <summary>
        /// Copia os itens para área de transferência
        /// </summary>
        /// <param name="items">Itens a serem copiados</param>
        /// <returns>true se copiou com sucesso, false se a cópia foi cancelada no evento <c>CopyingClipboard</c></returns>
        private bool CopyClipboard(IEnumerable items)
        {
            if (items == null)
                throw new ArgumentNullException("items");

            StringBuilder stbClipBoard = new StringBuilder();
            bool copiedToClipBoard = false;

            // Alimenta coleção que será disponibilizada nos Eventos CopyingClipBoard e CopiedClipBoard
            List<ItemInfo> itemsInfo = FillItemsInfo(items);

            if (this.OnCopyingClipboard(itemsInfo))
            {
                //Classifica coluna pela ordem da exibição para no caso de troca de posição de colunas manualmente.
                List<Column> columns = this.Columns.OrderBy(Column => Column.InternalColumn.VisiblePosition).ToList();

                //Preenche o nome das colunas
                for (int i = 0; i < columns.Count; i++)
                {
                    Column column = columns[i];

                    //Verifica o parametro AllowCopyClipBoard e Visible para saber se a coluna será exibida ou não
                    if (AllowCopyClipboard(column))
                    {
                        stbClipBoard.Append((string)ResourceProviderManager.GetResourceProvider().TryGetResource(column.Title));
                        if (i < columns.Count - 1)
                            stbClipBoard.Append("\t");
                    }
                }
                stbClipBoard.Append("\r\n");

                //Preenche os valores das colunas
                foreach (object item in items)
                {
                    for (int i = 0; i < columns.Count; i++)
                    {
                        Column column = columns[i];

                        //Verifica o parametro AllowCopy e Visible para saber se a coluna será copiada ou não
                        if (AllowCopyClipboard(column))
                        {
                            //Busca todos os membros de exibição da coluna
                            List<string> displayMembers = column.GetCopyClipboardProperties();

                            if (displayMembers.Count() > 0)
                            {
                                //Busca os PropertiesInfo de todos os membros de exibição
                                List<PropertyValueType> propertiesInfo = item.GetPropertyInfo(displayMembers);

                                if (propertiesInfo.Count() > 0)
                                {
                                    stbClipBoard.Append(FormatProperties(propertiesInfo, column.CopyClipboardStringFormat));
                                }
                            }
                            if (i < columns.Count - 1)
                                stbClipBoard.Append("\t");
                        }
                    }
                    stbClipBoard.Append("\r\n");
                }

                Clipboard.SetDataObject(stbClipBoard.ToString(), true);

                copiedToClipBoard = true;

                this.OnCopiedClipboard(itemsInfo);
            }

            return copiedToClipBoard;
        }
        #endregion

        #region CopyAllClipboard
        /// <summary>
        /// Indica se pode copiar todos os itens para área de transferência
        /// </summary>
        /// <returns>true se puder copiar para área de transferência, false se não puder</returns>
        protected bool CanCopyAllClipboard()
        {
            return !this.IsEditing && (this.Items.Count > 0);
        }

        /// <summary>
        /// Copia todos os itens para área de transferência
        /// </summary>
        /// <returns>true se copiou com sucesso, false se a cópia foi cancelada no evento <c>CopyingClipboard</c></returns>
        public bool CopyAllClipboard()
        {
            if (this.CanCopyAllClipboard())
            {
                return this.CopyClipboard(this.ItemsSource);
            }
            return false;
        }
        #endregion

        #region AllowCopyClipboard
        private bool AllowCopyClipboard(Column column)
        {
            bool allowCopyClipboard = false;
            bool? allowClipboardPropertyValue = null;

            //Verifica se a propriedade foi setada no Xaml
            LocalValueEnumerator locallySetProperties = column.GetLocalValueEnumerator();
            while (locallySetProperties.MoveNext())
            {
                DependencyProperty propertyAllowCopyClipBoard = (DependencyProperty)locallySetProperties.Current.Property;
                if (propertyAllowCopyClipBoard == Column.AllowCopyClipboardProperty)
                {
                    if (Convert.ToBoolean(propertyAllowCopyClipBoard.DefaultMetadata.DefaultValue))
                        allowClipboardPropertyValue = true;
                    else
                        allowClipboardPropertyValue = false;
                    break;
                }
            }

            //Caso exista AllowCopyClipBoard no Xaml - segue o valor que está definido 
            if (allowClipboardPropertyValue != null)
            {
                if (allowClipboardPropertyValue.Value)
                    allowCopyClipboard = true;
                else
                    allowCopyClipboard = false;
            }
            // Caso não exista AllowCopyClipBoard no Xaml - segue a propriedade Visible
            else
            {
                if (column.Visible)
                    allowCopyClipboard = true;
                else
                    allowCopyClipboard = false;
            }

            return allowCopyClipboard;

        }
        #endregion
    }

}
